home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / game / role / ZorkMachine_1_15.LHA / getopt.c < prev    next >
C/C++ Source or Header  |  1992-03-27  |  7KB  |  246 lines

  1. /****************************************************************************
  2.  * getopt():    Return the next user option on each iteration. 
  3.  *        This is a clone of the usual UNIX getopt() function.
  4.  *        If you have never used a getopt() before, you'll have to
  5.  *          read about it on any UNIX machine or other C system that
  6.  *          documents it.
  7.  *
  8.  * Author:    Daniel Barrett, barrett@cs.jhu.edu.
  9.  * Date:    February 20, 1991.
  10.  * Version:    1.1.
  11.  *
  12.  * License:    This code is placed in the Public Domain.
  13.  *        Give it away to anybody for free!
  14.  *        Use it for any purpose you like!
  15.  *
  16.  *        If you use this code in a program, please give me credit
  17.  *        for my work.  Thanks!
  18.  *
  19.  * Why I wrote it:
  20.  *
  21.  *        Because every other getopt() function I have ever seen
  22.  *         had source code that was difficult to understand.
  23.  *        I wrote this code to be very modular and readable.
  24.  *        I hope you find it instructive and/or helpful.
  25.  *
  26.  * REVISION HISTORY:
  27.  *    Version:    1.1
  28.  *    Date:        February 20, 1991.
  29.  *    Comments:    Bug fix in Pass().  Forgot to check that the
  30.  *            current argument is non-empty and starts with
  31.  *            a DASH.
  32.  *
  33.  *            Got rid of the unnecessary "g_" at the beginning
  34.  *            of each function name.  Since they're static, we
  35.  *            don't have to worry about duplication of names
  36.  *            by the calling program.
  37.  *
  38.  *    Version:    1.0
  39.  *    Date:        April 12, 1990.
  40.  *    Comments:    First released version.
  41.  *
  42.  ****************************************************************************/
  43.  
  44. #include <stdio.h>
  45. #include <string.h>
  46.  
  47. #undef NULL
  48. #define NULL 0L
  49.  
  50. /************************************************************************
  51. * Some constants.
  52. ************************************************************************/
  53.  
  54. #define    DASH        '-'    /* This preceeds an option. */
  55. #define    ARG_COMING    ':'    /* In the option string, this indicates that
  56.                  * that the option requires an argument. */
  57. #define    UNKNOWN_OPT    '?'    /* The char returned for unknown option. */
  58.  
  59. /************************************************************************
  60. * Internal error codes.
  61. ************************************************************************/
  62.  
  63. #define    ERROR_BAD_OPTION    1
  64. #define    ERROR_MISSING_ARGUMENT    2
  65.  
  66. /************************************************************************
  67. * Mnemonic macros.
  68. ************************************************************************/
  69.  
  70.  
  71.  
  72. /************************************************************************
  73. * ANSI function prototypes.
  74. ************************************************************************/
  75.  
  76. int        getopt(int argc, char *argv[], char *optString);
  77. static int    NextOption(char *argv[], char *optString);
  78. static int    RealOption(char *argv[], char *str, int *skip, int *ind,
  79.                  int opt);
  80. static void    HandleArgument(char *argv[], int *optind, int *skip);
  81. static void    Error(int err, int c);
  82. static void    Pass(char *argv[], int *optind, int *optsSkipped);
  83.  
  84. /************************************************************************
  85. * Global variables.  You must declare these externs in your program
  86. * if you want to see their values!
  87. ************************************************************************/
  88.  
  89. char    *optarg    = NULL;    /* This will point to a required argument, if any. */
  90. int    optind    = 1;    /* The index of the next argument in argv. */
  91. int    opterr    = 1;    /* 1 == print internal error messages.  0 else. */
  92. int    optopt;        /* The actual option letter that was found. */
  93.  
  94.  
  95. int getopt(int argc, char *argv[], char *optString)
  96. {
  97.     optarg = NULL;
  98.     if (optind < argc)        /* More arguments to check. */
  99.         return(NextOption(argv, optString));
  100.     else                /* We're done. */
  101.         return(EOF);
  102. }
  103.  
  104.  
  105. /* If the current argument does not begin with DASH, it is not an option.
  106.  * Return EOF.
  107.  * If we have ONLY a DASH, and nothing after it... return EOF as well.
  108.  * If we have a DASH followed immediately by another DASH, this is the
  109.  * special "--" option that means "no more options follow."  Return EOF.
  110.  * Otherwise, we have an actual option or list of options.  Process it. */
  111.  
  112. static int NextOption(char *argv[], char *optString)
  113. {
  114.     static int optsSkipped = 0;    /* In a single argv[i]. */
  115.  
  116.     if ((argv[optind][0] == DASH)
  117.     &&  ((optopt = argv[optind][1+optsSkipped]) != '\0'))
  118.     {
  119.         if (optopt == DASH)
  120.         {
  121.             optind++;
  122.             return(EOF);
  123.         }
  124.         else
  125.             return(RealOption(argv, optString, &optsSkipped,
  126.                         &optind, optopt));
  127.     }
  128.     else
  129.         return(EOF);
  130. }
  131.  
  132.  
  133. /* At this point, we know that argv[optind] is an option or list of
  134.  * options.  If this is a list of options, *optsSkipped tells us how
  135.  * many of those options have ALREADY been parsed on previous calls
  136.  * to getopt().
  137.  * If the option is not legal (not in optString), complain and return
  138.  * UNKNOWN_OPT.
  139.  * If the option requires no argument, just return the option letter.
  140.  * If the option requires an argument, call HandleArgument and return
  141.  * the option letter. */
  142.  
  143. static int RealOption(char *argv[], char *optString, int *optsSkipped,
  144.             int *optind, int optopt)
  145. {
  146.     char *where;
  147.  
  148.     (*optsSkipped)++;
  149.     if (where = strchr(optString, optopt))
  150.     {
  151.         if (*(where+1) == ARG_COMING)
  152.             HandleArgument(argv, optind, optsSkipped);
  153.  
  154.         Pass(argv, optind, optsSkipped);
  155.         return(optopt);
  156.     }
  157.     else
  158.     {
  159.         Error(ERROR_BAD_OPTION, optopt);
  160.         Pass(argv, optind, optsSkipped);
  161.         return(UNKNOWN_OPT);
  162.     }
  163. }
  164.  
  165.  
  166. /* We have an option in argv[optind] that requires an argument.  If there
  167.  * is no whitespace after the option letter itself, take the rest of
  168.  * argv[optind] to be the argument.
  169.  * If there IS whitespace after the option letter, take argv[optind+1] to
  170.  * be the argument.
  171.  * Otherwise, if there is NO argument, complain! */
  172.  
  173. static void HandleArgument(char *argv[], int *optind, int *optsSkipped)
  174. {
  175.     if (argv[*optind][1+(*optsSkipped)])
  176.         optarg = argv[*optind] + 1 + (*optsSkipped);
  177.     else if (argv[(*optind)+1])
  178.     {
  179.         optarg = argv[(*optind)+1];
  180.         (*optind)++;
  181.     }
  182.     else
  183.         Error(ERROR_MISSING_ARGUMENT, optopt);
  184.  
  185.     (*optsSkipped) = 0;
  186.     (*optind)++;
  187. }
  188.  
  189.  
  190. /* Print an appropriate error message. */
  191.  
  192. static void Error(int err, int c)
  193. {
  194.     static char *optmsg = "Illegal option.\n";
  195.     static char *argmsg = "An argument is required, but missing.\n";
  196.  
  197.     if (opterr)
  198.     {
  199.         if (err == ERROR_BAD_OPTION)
  200.             fprintf(stderr, "-%c: %s", c, optmsg);
  201.         else if (err == ERROR_MISSING_ARGUMENT)
  202.             fprintf(stderr, "-%c: %s", c, argmsg);
  203.  
  204.         else    /* Sanity check! */
  205.             fprintf(stderr, "-%c: an unknown error occurred\n",
  206.                 c);
  207.     }
  208. }
  209.  
  210.  
  211. /* We have reached the end of argv[optind]... there are no more options
  212.  * in it to parse.  Skip to the next item in argv. */
  213.  
  214. static void Pass(char *argv[], int *optind, int *optsSkipped)
  215. {
  216.     if (argv[*optind]
  217.     &&  (argv[*optind][0] == DASH)
  218.     &&  (argv[*optind][1+(*optsSkipped)] == NULL))
  219.     {
  220.         (*optind)++;
  221.         (*optsSkipped) = 0;
  222.     }
  223. }
  224.  
  225. /***************************************************************************
  226. * A test program.  Compile this file with -DTESTME as an option.
  227. ***************************************************************************/
  228.  
  229. #ifdef TESTME
  230. main(int argc, char *argv[])
  231. {
  232.     char c;
  233.  
  234.     while ((c = getopt(argc, argv, "a:b:cde")) != EOF)
  235.         {
  236.         printf("OPTION %c", c);
  237.         if ((c == 'a') || (c == 'b'))
  238.             printf(", %s\n", optarg);
  239.         else
  240.             printf("\n");
  241.         printf("argc=%d, optind=%d\n", argc, optind);
  242.     }
  243.     exit(0);
  244. }
  245. #endif
  246.